package org.jsola.hr.service.impl;

import org.jsola.core.Page;
import org.jsola.exception.ParamException;
import org.jsola.hr.common.ExampleKit;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.dao.IPolicyCourierTypeDAO;
import org.jsola.hr.dto.PolicyCourierTypeAddDTO;
import org.jsola.hr.dto.PolicyCourierTypeUpdateDTO;
import org.jsola.hr.dto.UpdatePolicySortDTO;
import org.jsola.hr.entity.PolicyCourierDO;
import org.jsola.hr.entity.PolicyCourierTypeDO;
import org.jsola.hr.query.PolicyCourierTypeQuery;
import org.jsola.hr.service.IPolicyCourierService;
import org.jsola.hr.service.IPolicyCourierTypeService;
import org.jsola.hr.vo.PolicyCourierTypeListVO;
import org.jsola.hr.vo.PolicyCourierTypeVO;
import org.jsola.user.common.PinyinKit;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 政策速递类型
 *
 * @author zhr
 */
@Service("hrPolicyCourierTypeServiceImpl")
public class PolicyCourierTypeServiceImpl implements IPolicyCourierTypeService {

    @Autowired
    private IPolicyCourierTypeDAO policyCourierTypeDAO;

    @Autowired
    private IPolicyCourierService policyCourierService;

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public PolicyCourierTypeVO save(PolicyCourierTypeAddDTO policyCourierTypeAddDTO, TokenUser tokenUser) {
        // 校验名称是否重复
        this.checkName(null, policyCourierTypeAddDTO.getName(), tokenUser);
        // 转DO
        PolicyCourierTypeDO policyCourierTypeDO = policyCourierTypeAddDTO.to(PolicyCourierTypeDO.class);
        // code
        policyCourierTypeDO.setCode(PinyinKit.nameToPinyin(policyCourierTypeAddDTO.getName()));
        if (ObjectUtils.isEmpty(policyCourierTypeAddDTO.getSort())) {
            policyCourierTypeDO.setSort(1);
        }
        List<PolicyCourierTypeDO> policyCourierTypeList = selectTypeBySite(tokenUser);
        Integer maxSort = policyCourierTypeList.stream().map(PolicyCourierTypeDO::getSort)
                .max(Integer::compare).orElse(1);
        policyCourierTypeDO.setSort(maxSort + 1);
        // 保存
        policyCourierTypeDO = save(policyCourierTypeDO, tokenUser.getSiteId(), tokenUser.getUserId());
        return policyCourierTypeDO.to(PolicyCourierTypeVO.class);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int update(PolicyCourierTypeUpdateDTO policyCourierTypeUpdateDTO, TokenUser tokenUser) {
        // 校验名称是否重复
        this.checkName(policyCourierTypeUpdateDTO.getId(), policyCourierTypeUpdateDTO.getName(), tokenUser);
        PolicyCourierTypeVO type = this.selectById(policyCourierTypeUpdateDTO.getId(), tokenUser.getSiteId());
        //转DO
        PolicyCourierTypeDO policyCourierTypeDO = policyCourierTypeUpdateDTO.to(PolicyCourierTypeDO.class);
        // 如果两个名称不一样则更新code
        if (!type.getName().equals(policyCourierTypeUpdateDTO.getName())) {
            String newCode = PinyinKit.nameToPinyin(policyCourierTypeUpdateDTO.getName());
            policyCourierTypeDO.setCode(newCode);
            // 更新code的时候需要把政策速递里面的文章的code一块改掉
            policyCourierService.updatePolicyCourierCode(newCode, type.getCode(), tokenUser);
        }
        //根据主键更新，只更新非null值
        return updateByIdSelective(policyCourierTypeDO, tokenUser.getSiteId(), tokenUser.getUserId());
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteByIds(TokenUser tokenUser, String... policyCourierTypeIds) {
        // 删除分类时同步把文章也删除
        for (String policyCourierTypeId : policyCourierTypeIds) {
            PolicyCourierTypeVO policyCourierType = selectById(policyCourierTypeId, tokenUser.getSiteId());
            policyCourierService.deleteByCode(policyCourierType.getCode(), tokenUser);
        }
        return logicalDeleteByIds(tokenUser.getSiteId(), tokenUser.getUserId(), (Object[]) policyCourierTypeIds);
    }


    @Override
    public PolicyCourierTypeVO selectById(String policyCourierTypeId, String siteId) {
        PolicyCourierTypeDO policyCourierTypeDO = selectDOById(policyCourierTypeId, siteId);
        if (policyCourierTypeDO == null) {
            return null;
        }
        return policyCourierTypeDO.to(PolicyCourierTypeVO.class);
    }

    @Override
    public List<PolicyCourierTypeListVO> select(PolicyCourierTypeQuery policyCourierTypeQuery, String siteId) {
        List<PolicyCourierTypeDO> policyCourierTypeDOList = selectDO(policyCourierTypeQuery, siteId);
        if (CollectionUtils.isEmpty(policyCourierTypeDOList)) {
            return policyCourierTypeDOList == null ? null : new ArrayList<>();
        }
        return policyCourierTypeDOList.stream()
                .map(policyCourierTypeDO -> policyCourierTypeDO.to(PolicyCourierTypeListVO.class))
                .collect(Collectors.toList());
    }

    @Override
    public int selectCount(PolicyCourierTypeQuery policyCourierTypeQuery, String siteId) {
        Example example = buildExample(policyCourierTypeQuery, siteId);
        return policyCourierTypeDAO.selectCountByExample(example);
    }

    @Override
    public Page<PolicyCourierTypeListVO> selectPage(PolicyCourierTypeQuery policyCourierTypeQuery, String siteId) {
        Example example = buildExample(policyCourierTypeQuery, siteId);
        Page<PolicyCourierTypeDO> page = policyCourierTypeDAO.selectPageByExample(example,
                policyCourierTypeQuery.getPageNo(),
                policyCourierTypeQuery.getPageSize());

        return page.to(PolicyCourierTypeListVO.class);
    }

    @Override
    public PolicyCourierTypeDO selectDOById(String policyCourierTypeId, String siteId) {
        return listById(policyCourierTypeId, siteId);
    }

    @Override
    public List<PolicyCourierTypeDO> selectDO(PolicyCourierTypeQuery policyCourierTypeQuery, String siteId) {
        Example example = buildExample(policyCourierTypeQuery, siteId);
        return policyCourierTypeDAO.selectByExample(example);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public void updateSort(List<UpdatePolicySortDTO> updateSortList) {
        if (!CollectionUtils.isEmpty(updateSortList)) {
            List<PolicyCourierTypeDO> updateList = updateSortList.stream()
                    .map(updateSort -> updateSort.to(PolicyCourierTypeDO.class))
                    .collect(Collectors.toList());
            for (PolicyCourierTypeDO PolicyCourierType : updateList) {
                policyCourierTypeDAO.updateByPrimaryKeySelective(PolicyCourierType);
            }
        }
    }

    @Override
    public List<PolicyCourierTypeDO> selectTypeBySite(TokenUser tokenUser) {
        Example example = new Example(PolicyCourierTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId());
        return policyCourierTypeDAO.selectByExample(example);
    }

    /**
     * 校验类型名称是否重复
     */
    private void checkName(String id, String name, TokenUser tokenUser) {
        Example example = new Example(PolicyCourierTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", tokenUser.getSiteId())
                .andEqualTo("name", name);
        if (!StringUtils.isEmpty(id)) {
            example.and().andNotEqualTo("id", id);
        }
        List<PolicyCourierTypeDO> typeList = policyCourierTypeDAO.selectByExample(example);
        if (!CollectionUtils.isEmpty(typeList)) {
            throw new ParamException("政策速递类型名称重复");
        }
    }

    /**
     * 根据查询参数，构建example
     *
     * @param policyCourierTypeQuery 查询参数
     * @param siteId                 所属站点id
     * @return example
     */
    private Example buildExample(PolicyCourierTypeQuery policyCourierTypeQuery, String siteId) {
        Example example = new Example(PolicyCourierTypeDO.class);
        example.and()
                .andEqualTo("valid", true)
                .andEqualTo("siteId", siteId);
        if (!StringUtils.isEmpty(policyCourierTypeQuery.getTypeName())) {
            example.and().andLike("name", "%" + policyCourierTypeQuery.getTypeName() + "%");
        }
        // 排序
        example.orderBy("sort").orderBy("gmtCreate").desc();
        return example;
    }
}




